# plugs/relay.py
#
#

""" relay between bot/channels """

__copyright__ = 'this file is in the public domain'

from gozerbot.commands import cmnds
from gozerbot.examples import examples
from gozerbot.callbacks import callbacks
from gozerbot.fleet import fleet
from gozerbot.monitor import saymonitor
from gozerbot.datadir import datadir
from gozerbot.pdol import Pdol
from gozerbot.plughelp import plughelp
import time

plughelp.add('relay', 'relay between fleet bots or channels')

class Relay(Pdol):

    """ relay is implemented as a pickled dict of lists """

    def check(self, botname, channel, txt):
        """ check if we relay on (botname, channel) .. if so do output """
        if self.data.has_key((botname, channel)):
            for i in self.data[(botname, channel)]:
                if i != (botname, channel):
                    bot = fleet.byname(i[0])
                    if bot:
                        if not bot.stopped:
                            time.sleep(1)
                            bot.outputnolog(i[1], txt, 'msg')

    def wouldrelay(self, botname, channel):
        """ check if (botname, channel) would relay """
        return self.data.has_key((botname, channel))

    def channels(self, botname):
        """ show channels that are relayed on bot """
        result = []
        for i in self.data.keys():
            if i[0] == botname:
                result.append(i[1])
        return result

def init():
    """ called after reload """
    saymonitor.add('relay', saycb, prerelaysay)
    return 1
    
relay = Relay(datadir + '/relay')

def cbrelaymode(bot, ievent):
    """ callback for MODE events """
    relay.check(bot.name, ievent.channel, "[bot] mode change on %s by %s \
(%s): %s" % (bot.server, ievent.nick, ievent.userhost, ievent.postfix))

callbacks.add('MODE', cbrelaymode, None)

def prerelay(bot, ievent):
    """ precondition on PRIVMSG events """
    return relay.wouldrelay(bot.name, ievent.channel)

def cbrelaypriv(bot, ievent):
    """ PRIVMSG relay callback """
    if ievent.txt[0] == '\001' and ievent.txt.find('ACTION') != -1:
        result = "* [%s] %s" % (ievent.nick, ievent.txt[8:-1])
    else:
        result = "[%s] %s" % (ievent.nick, ievent.txt)
    relay.check(bot.name, ievent.channel, result)

callbacks.add('PRIVMSG', cbrelaypriv, prerelay)

def cbrelayjoin(bot, ievent):
    """ JOIN relay callback """
    relay.check(bot.name, ievent.channel, "%s joined %s on %s" % \
(ievent.nick, ievent.channel, bot.name))

callbacks.add('JOIN', cbrelayjoin, prerelay)

def cbrelaypart(bot, ievent):
    """ PART relay callback """
    relay.check(bot.name, ievent.channel, "%s left %s on %s" % \
(ievent.nick, ievent.channel, bot.name))

callbacks.add('PART', cbrelaypart, prerelay)

def prerelaysay(botname, printto, txt, who, how, fromm):
    """ precondition on bot.say callbacks """
    return relay.wouldrelay(botname, printto)

def saycb(botname, printto, txt, who, how, fromm):
    """ callback for bots output """
    relay.check(botname, printto, "[bot] %s" % txt)

def handle_relaylist(bot, ievent):
    """ realy-list .. list all relays """
    result = ""
    for item, value in relay.data.iteritems():
        tempstr = ""
        for relayto in value:
            tempstr += "(%s,%s) .. " % (relayto[0], relayto[1])
        tempstr = tempstr[:-4]
        result += "(%s,%s) = %s, " % (item[0], item[1], tempstr)
    if result:
        ievent.reply(result[:-2])
    else:
        ievent.reply('no relays')

cmnds.add('relay-list', handle_relaylist, 'OPER')
examples.add('relay-list', 'list the relays', 'relay-list')

def handle_relayadd(bot, ievent):
    """ relay-add <botname> <channel> <botname> <channel> .. add a relay """
    try:
        (botnamefrom, channelfrom, botnameto, channelto) = ievent.args
    except ValueError:
        ievent.missing('<botnamefrom> <channelfrom> <botnameto> <channelto>')
        return
    relay[(botnamefrom, channelfrom)] = (botnameto, channelto)
    relay.save()
    ievent.reply('relay added')

cmnds.add('relay-add', handle_relayadd, 'OPER')
examples.add('relay-add', 'relay-add <botname> <channel> <botname> \
<channel> .. add bot/channel to relay', 'relay-add main #r5 main #bartbot')

def handle_relaydel(bot, ievent):
    """ relay-del <botname> <channel> <botname> <channel> .. delete a relay """
    try:
        (botnamefrom, channelfrom, botnameto, channelto) = ievent.args
    except ValueError:
        ievent.missing('<botnamefrom> <channelfrom> <botnameto> <channelto>')
        return
    try:
        relay.data[(botnamefrom, channelfrom)].remove((botnameto, channelto))
    except (KeyError, ValueError):
        ievent.reply("there is no %s %s - %s %s relay" % \
(botnamefrom, channelfrom, botnameto, channelto))
        return
    if len(relay[(botnamefrom, channelfrom)]) == 0:
        del relay[(botnamefrom, channelfrom)]
    relay.save()
    ievent.reply('relay deleted')

cmnds.add('relay-del', handle_relaydel, 'OPER')
examples.add('relay-del', 'relay-del <botname> <channel> <botname> \
<channel> .. delete bot/channel from relay', 'relay-del main #gozerbot \
main #dunkbots')
